package com.gzx.plugin.tjzy.modular.liaison.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.gzx.plugin.tjzy.modular.complaint.service.GzxComplaintUserService;
import com.gzx.plugin.tjzy.modular.liaison.entity.GzxDebtorLiaison;
import com.gzx.plugin.tjzy.modular.liaison.entity.bo.GzxDebtorLiaisonAddOrEditBo;
import com.gzx.plugin.tjzy.modular.liaison.entity.bo.GzxDebtorLiaisonQueryBo;
import com.gzx.plugin.tjzy.modular.liaison.entity.vo.GzxDebtorLiaisonImportVo;
import com.gzx.plugin.tjzy.modular.liaison.entity.vo.GzxDebtorLiaisonVo;
import com.gzx.plugin.tjzy.modular.liaison.listener.LiaisonExcelListener;
import com.gzx.plugin.tjzy.modular.liaison.mapper.GzxDebtorLiaisonMapper;
import com.gzx.plugin.tjzy.modular.liaison.service.GzxDebtorLiaisonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.common.cache.CommonCacheOperator;
import vip.xiaonuo.common.consts.IntConstant;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.util.*;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static org.apache.commons.lang.StringEscapeUtils.escapeSql;

/**
 * @author zjt
 * @description
 * @date 2024/12/4 15:32
 */
@Slf4j
@Service
@DS("tjzy")
@RequiredArgsConstructor
public class GzxDebtorLiaisonServiceImpl implements GzxDebtorLiaisonService {

    private final GzxDebtorLiaisonMapper debtorLiaisonMapper;

    private final GzxComplaintUserService complaintUserService;

    private final CommonCacheOperator cacheOperator;

    /**
     * 欠款联系人分页查询
     *
     * @param debtorLiaisonQueryBo
     * @return
     */
    @Override
    @DS("tjzy")
    public Page<GzxDebtorLiaisonVo> pageList(GzxDebtorLiaisonQueryBo debtorLiaisonQueryBo) {
        Page<GzxDebtorLiaisonVo> result = debtorLiaisonMapper.selectVoPage(new Page<>(debtorLiaisonQueryBo.getCurrent(), debtorLiaisonQueryBo.getSize()), Wrappers.<GzxDebtorLiaison>lambdaQuery()
                .eq(GzxDebtorLiaison::getDebtorCardId, CommonCryptogramUtil.doSm1AesEncrypt(debtorLiaisonQueryBo.getDebtorCardId()))
                .orderByDesc(GzxDebtorLiaison::getId));
        result.getRecords().forEach(debtorLiaison -> debtorLiaison.setTodayCallCount(cacheOperator.getIncrAtomic(String.valueOf(debtorLiaison.getLiaisonPhone()))));
        return result;
    }

    /**
     * 三方联系人导入
     *
     * @param multipartFile
     */
    @Override
    @DS("tjzy")
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(MultipartFile multipartFile) throws IOException {
        List<GzxDebtorLiaisonImportVo> debtorLiaisonImportVoList = CommonExcelUtil.importExcel(multipartFile, GzxDebtorLiaisonImportVo.class, new LiaisonExcelListener());
        if (CollectionUtil.isEmpty(debtorLiaisonImportVoList)) {
            throw new CommonException("导入Excel为空");
        }
        List<GzxDebtorLiaison> debtorRelationPhoneList = tileList(debtorLiaisonImportVoList);
        if (CollectionUtil.isNotEmpty(debtorRelationPhoneList)) {
            long insertTime = System.currentTimeMillis();
            List<List<GzxDebtorLiaison>> liaisonBatchList = Lists.partition(debtorRelationPhoneList, IntConstant.VALUE_1000);
            String userId = StpLoginUserUtil.getLoginUser().getId();
            String tenantId = StpLoginUserUtil.getLoginUser().getTenantId();
            String currDate = CommonDateUtil.getCurrentTimeStr();
            for (List<GzxDebtorLiaison> liaisonBatch : liaisonBatchList) {
                long batchTime = System.currentTimeMillis();
                String sql = liaisonBatch.stream()
                        .map(s -> String.format("('%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s')",
                                escapeSql(s.getProjectCode()),
                                escapeSql(CommonCryptogramUtil.doSm1AesEncrypt(s.getDebtorCardId())),
                                escapeSql("1"),
                                escapeSql(s.getRelationship()),
                                escapeSql(s.getLiaisonName()),
                                escapeSql(CommonCryptogramUtil.doSm1AesEncrypt(s.getLiaisonPhone())),
                                escapeSql("2"),
                                escapeSql(s.getRemark()),
                                escapeSql(tenantId),
                                escapeSql(userId),
                                escapeSql(currDate)))
                        .collect(Collectors.joining(", "));
                debtorLiaisonMapper.insertBatchBySql(sql.replace("'null'", "null"));
                log.info("批量添加三方联系人，共计：{}条，耗时：{}", liaisonBatch.size(), System.currentTimeMillis() - batchTime);
                CommonSleepUtil.sleep(IntConstant.VALUE_100);
            }
            log.info("添加三方联系人，共计：{}条，耗时：{}", debtorRelationPhoneList.size(), System.currentTimeMillis() - insertTime);
        }
    }

    /**
     * 批量新增三方联系人
     *
     * @param debtorLiaisonList
     */
    @Override
    @DS("tjzy")
    @Transactional(rollbackFor = Exception.class)
    public void insertBatch(List<GzxDebtorLiaison> debtorLiaisonList) {
        String currDate = CommonDateUtil.getCurrentTimeStr();
        List<List<GzxDebtorLiaison>> liaisonBatchList = Lists.partition(debtorLiaisonList, IntConstant.VALUE_1000);
        for (List<GzxDebtorLiaison> batch : liaisonBatchList) {
            String batchSql = batch.stream()
                    .map(s -> String.format("('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
                            escapeSql(s.getProjectCode()),
                            escapeSql(CommonCryptogramUtil.doSm1AesEncrypt(s.getDebtorCardId())),
                            escapeSql(s.getRelationship()),
                            escapeSql(s.getLiaisonName()),
                            escapeSql(CommonCryptogramUtil.doSm1AesEncrypt(s.getLiaisonPhone())),
                            escapeSql(s.getWorkAddress()),
                            escapeSql(String.valueOf(s.getPhoneSource())),
                            escapeSql(s.getTenantId()),
                            escapeSql(s.getCreateUser()),
                            escapeSql(currDate)
                    ))
                    .collect(Collectors.joining(", "));
            debtorLiaisonMapper.insertBatch(batchSql.replace("'null'", "null"));
            CommonSleepUtil.sleep100();
        }
    }

    /**
     * 获取欠款联系人的明文手机号
     *
     * @param id      主键
     * @param isCatch 是否保存到缓存
     * @return 欠款联系人的明文手机号
     */
    @Override
    @DS("tjzy")
    public Map getLiaisonPhoneById(Long id, boolean isCatch) {
        Map<String, String> hashMap = new HashMap<>();
        GzxDebtorLiaison debtorLiaison = debtorLiaisonMapper.selectById(id);
        if (debtorLiaison == null) {
            return null;
        }
        hashMap.put("liaisonPhone", debtorLiaison.getLiaisonPhone());
        if (isCatch) {
            List<String> list = complaintUserService.checkComplaintUser(List.of(debtorLiaison.getDebtorCardId()));
            if (CollectionUtil.isNotEmpty(list)) {
                hashMap.put("msg", list.toString());
                return hashMap;
            }
        }
        return hashMap;
    }

    /**
     * 新增欠款联系人
     *
     * @param debtorLiaisonAddOrEditBo
     */
    @Override
    @DS("tjzy")
    public void addOrEdit(GzxDebtorLiaisonAddOrEditBo debtorLiaisonAddOrEditBo) {
        GzxDebtorLiaison debtorLiaison = MapstructUtils.convert(debtorLiaisonAddOrEditBo, GzxDebtorLiaison.class);
        if (debtorLiaison.getId() == null) {
            //如果已存在，则不做任何操作
            GzxDebtorLiaisonVo liaison = debtorLiaisonMapper.selectVoOne(Wrappers.<GzxDebtorLiaison>lambdaQuery()
                    .eq(GzxDebtorLiaison::getDebtorCardId, CommonCryptogramUtil.doSm1AesEncrypt(debtorLiaison.getDebtorCardId()))
                    .eq(GzxDebtorLiaison::getLiaisonPhone, CommonCryptogramUtil.doSm1AesEncrypt(debtorLiaison.getLiaisonPhone()))
                    .eq(GzxDebtorLiaison::getLiaisonName, debtorLiaison.getLiaisonName())
                    .last("limit 1")
            );
            if (!Objects.isNull(liaison)) {
                throw new CommonException("该联系人已存在");
            }
            debtorLiaison.setPhoneSource(3);
            debtorLiaisonMapper.insert(debtorLiaison);
        } else {
            debtorLiaison.setLiaisonPhone(null);
            debtorLiaisonMapper.updateById(debtorLiaison);
        }
    }

    /**
     * 通过ID删除联系人
     *
     * @param id
     * @return
     */
    @Override
    @DS("tjzy")
    public void deleteById(Long id) {
        debtorLiaisonMapper.deleteById(id);
    }

    /**
     * 手机号今日拨打次数
     *
     * @param liaisonPhone
     */
    @Override
    @DS("tjzy")
    public void addPhoneTodayCallCount(String liaisonPhone) {
        cacheOperator.getIncrAtomic(liaisonPhone, CommonDateUtil.getTodayDuration() + new Random().nextInt(600));
    }

    /**
     * 查询联系人
     *
     * @param queryWrapper
     * @return
     */
    @Override
    @DS("tjzy")
    public List<GzxDebtorLiaison> selectList(LambdaQueryWrapper<GzxDebtorLiaison> queryWrapper) {
        return debtorLiaisonMapper.selectList(queryWrapper);
    }

    private List<GzxDebtorLiaison> tileList(List<GzxDebtorLiaisonImportVo> debtorLiaisonImportVoList) {
        List<GzxDebtorLiaison> debtorLiaisonList = new ArrayList<>();
        for (GzxDebtorLiaisonImportVo importVo : debtorLiaisonImportVoList) {
            for (String phoneNumber : importVo.getLiaisonPhoneList()) {
                GzxDebtorLiaison debtorLiaison = new GzxDebtorLiaison();
                debtorLiaison.setDebtorCardId(importVo.getDebtorCardId());
                debtorLiaison.setLiaisonName(importVo.getLiaisonName());
                debtorLiaison.setRelationship(importVo.getRelationship());
                debtorLiaison.setWorkAddress(importVo.getWorkAddress());
                debtorLiaison.setRemark(importVo.getRemark());
                debtorLiaison.setLiaisonPhone(phoneNumber);
                debtorLiaisonList.add(debtorLiaison);
            }
        }
        return debtorLiaisonList;
    }
}
